package com.example.bledemo

import android.Manifest
import android.bluetooth.*
import android.bluetooth.BluetoothDevice.TRANSPORT_LE
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity
import com.example.bledemo.databinding.ActivityMainBinding
import java.util.*
import android.text.TextUtils

import android.bluetooth.BluetoothGattCharacteristic

import android.bluetooth.BluetoothGattService

import android.widget.TextView
import java.lang.StringBuilder
import android.bluetooth.BluetoothGatt

import android.bluetooth.BluetoothGattCallback

import android.bluetooth.BluetoothDevice

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothAdapter.LeScanCallback
import com.example.bledemo.HexUtil.encodeHexStr
import java.lang.Exception


class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var mBluetoothManager: BluetoothManager
    private lateinit var mBluetoothAdapter: BluetoothAdapter
    private lateinit var mBluetoothGatt: BluetoothGatt
    private var isScanning = false
    private var isConnecting = false
    private lateinit var mDatas: MutableList<BluetoothDevice>
    private lateinit var mRssis: MutableList<Int>
    private lateinit var mAdapter: BleAdapter

    // 服务和特征值
    private var write_UUID_service: UUID? = null
    private var write_UUID_chara: UUID? = null
    private var read_UUID_service: UUID? = null
    private var read_UUID_chara: UUID? = null
    private var notify_UUID_service: UUID? = null
    private var notify_UUID_chara: UUID? = null
    private var indicate_UUID_service: UUID? = null
    private var indicate_UUID_chara: UUID? = null
    private val hex = "7B46363941373237323532443741397D"

    companion object {
        const val TAG = "### MainActivity"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initView()
        initData()
        initBluetooth()
    }

    private fun initView() {
        binding.btnRead.setOnClickListener { readData() }
        binding.btnWrite.setOnClickListener { writeData() }
        binding.ivSerBleStatus.setOnClickListener {
            if (isScanning) {
                binding.tvSerBindStatus.text = "停止搜索"
                stopScanDevice()
            } else {
                // checkPermissions()
            }
        }
        binding.bleListView.setOnItemClickListener {_, _, position, _ ->
            if (isScanning) {
                stopScanDevice()
            }
            if (!isConnecting) {
                isConnecting = true
                val device: BluetoothDevice = mDatas.get(position)
                binding.tvSerBindStatus.text = "连接中"
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mBluetoothGatt = device.connectGatt(this@MainActivity, true, gattCallback, TRANSPORT_LE)
                } else {
                    mBluetoothGatt = device.connectGatt(this@MainActivity, true, gattCallback)
                }
            }
        }
    }

    private fun initData() {
        mDatas = mutableListOf()
        mRssis = mutableListOf()
        mAdapter = BleAdapter(this, mDatas, mRssis)
        binding.bleListView.adapter = mAdapter
    }

    private fun initBluetooth() {
        mBluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
        mBluetoothAdapter = mBluetoothManager.adapter
        if (!mBluetoothAdapter.isEnabled) {
            val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(intent, 0)
        }
    }

    private fun readData() {
        val characteristic: BluetoothGattCharacteristic = mBluetoothGatt.getService(read_UUID_service)
            .getCharacteristic(read_UUID_chara)
        mBluetoothGatt.readCharacteristic(characteristic)
    }

    /**
     * 开始扫描 10秒后自动停止
     */
    private fun scanDevice() {
        binding.tvSerBindStatus.text = "正在搜索"
        isScanning = true
        binding.progressSerBluetooth.visibility = View.VISIBLE
        mBluetoothAdapter.startLeScan(scanCallback)
        Handler().postDelayed(Runnable { // 结束扫描
            mBluetoothAdapter.stopLeScan(scanCallback)
            runOnUiThread {
                isScanning = false
                binding.progressSerBluetooth.visibility = View.GONE
                binding.tvSerBindStatus.text = "搜索已结束"
            }
        }, 10000)
    }

    /**
     * 停止扫描
     */
    private fun stopScanDevice() {
        isScanning = false
        binding.progressSerBluetooth.visibility = View.GONE
        mBluetoothAdapter.stopLeScan(scanCallback)
    }

    var scanCallback =
        LeScanCallback { device, rssi, scanRecord ->
            Log.e(TAG, "run: scanning...")
            if (!mDatas.contains(device)) {
                mDatas.add(device)
                mRssis.add(rssi)
                mAdapter.notifyDataSetChanged()
            }
        }

    private val gattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
        /**
         * 断开或连接 状态发生变化时调用
         */
        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            Log.e(TAG, "onConnectionStateChange()")
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //连接成功
                if (newState == BluetoothGatt.STATE_CONNECTED) {
                    Log.e(TAG, "连接成功")
                    //发现服务
                    gatt.discoverServices()
                }
            } else {
                //连接失败
                Log.e(TAG, "失败==$status")
                mBluetoothGatt.close()
                isConnecting = false
            }
        }

        /**
         * 发现设备（真正建立连接）
         */
        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            super.onServicesDiscovered(gatt, status)
            //直到这里才是真正建立了可通信的连接
            isConnecting = false
            Log.e(TAG, "onServicesDiscovered()---建立连接")
            //获取初始化服务和特征值
            initServiceAndChara()
            //订阅通知
            mBluetoothGatt.setCharacteristicNotification(
                mBluetoothGatt.getService(notify_UUID_service).getCharacteristic(notify_UUID_chara), true
            )
            runOnUiThread {
                binding.bleListView.visibility = View.GONE
                binding.operaView.visibility = View.VISIBLE
                binding.tvSerBindStatus.text = "已连接"
            }
        }

        /**
         * 读操作的回调
         */
        override fun onCharacteristicRead(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            status: Int
        ) {
            super.onCharacteristicRead(gatt, characteristic, status)
            Log.e(TAG, "onCharacteristicRead()")
        }

        /**
         * 写操作的回调
         */
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            Log.e(TAG, "onCharacteristicWrite()  status=" + status + ",value=" +
                    encodeHexStr(characteristic.value)
            )
        }

        /**
         * 接收到硬件返回的数据
         */
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic
        ) {
            super.onCharacteristicChanged(gatt, characteristic)
            Log.e(TAG, "onCharacteristicChanged()" + characteristic.value)
            val data = characteristic.value
            runOnUiThread { addText(binding.tvResponse, bytes2hex(data)!!) }
        }
    }

    /**
     * 检查权限

    private fun checkPermissions() {
        val rxPermissions = RxPermissions(this@MainActivity)
        rxPermissions.request(Manifest.permission.ACCESS_FINE_LOCATION)
            .subscribe(object : Consumer<Boolean?>() {
                @Throws(Exception::class)
                fun accept(aBoolean: Boolean) {
                    if (aBoolean) {
                        // 用户已经同意该权限
                        scanDevice()
                    } else {
                        // 用户拒绝了该权限，并且选中『不再询问』
                        ToastUtils.showLong("用户开启权限后才能使用")
                    }
                }
            })
    }*/


    private fun initServiceAndChara() {
        val bluetoothGattServices = mBluetoothGatt.services
        for (bluetoothGattService in bluetoothGattServices) {
            val characteristics = bluetoothGattService.characteristics
            for (characteristic in characteristics) {
                val charaProp = characteristic.properties
                if (charaProp and BluetoothGattCharacteristic.PROPERTY_READ > 0) {
                    read_UUID_chara = characteristic.uuid
                    read_UUID_service = bluetoothGattService.uuid
                    Log.e(TAG,"read_chara=$read_UUID_chara----read_service=$read_UUID_service")
                }
                if (charaProp and BluetoothGattCharacteristic.PROPERTY_WRITE > 0) {
                    write_UUID_chara = characteristic.uuid
                    write_UUID_service = bluetoothGattService.uuid
                    Log.e(TAG,"write_chara=$write_UUID_chara----write_service=$write_UUID_service")
                }
                if (charaProp and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE > 0) {
                    write_UUID_chara = characteristic.uuid
                    write_UUID_service = bluetoothGattService.uuid
                    Log.e(TAG, "write_chara=$write_UUID_chara----write_service=$write_UUID_service")
                }
                if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
                    notify_UUID_chara = characteristic.uuid
                    notify_UUID_service = bluetoothGattService.uuid
                    Log.e(TAG, "notify_chara=$notify_UUID_chara----notify_service=$notify_UUID_service")
                }
                if (charaProp and BluetoothGattCharacteristic.PROPERTY_INDICATE > 0) {
                    indicate_UUID_chara = characteristic.uuid
                    indicate_UUID_service = bluetoothGattService.uuid
                    Log.e(TAG, "indicate_chara=$indicate_UUID_chara----indicate_service=$indicate_UUID_service")
                }
            }
        }
    }

    private fun addText(textView: TextView, content: String) {
        textView.append(content)
        textView.append("\n")
        val offset = textView.lineCount * textView.lineHeight
        if (offset > textView.height) {
            textView.scrollTo(0, offset - textView.height)
        }
    }

    private fun writeData() {
        val service = mBluetoothGatt.getService(write_UUID_service)
        val charaWrite = service.getCharacteristic(write_UUID_chara)

        val content: String = binding.etWrite.text.toString()
        val data: ByteArray = if (!TextUtils.isEmpty(content)) {
            HexUtil.hexStringToBytes(content) as ByteArray
        } else {
            HexUtil.hexStringToBytes(hex) as ByteArray
        }
        if (data.size > 20) { //数据大于个字节 分批次写入
            Log.e(TAG, "writeData: length=" + data.size)
            var num = 0
            num = if (data.size % 20 != 0) {
                data.size / 20 + 1
            } else {
                data.size / 20
            }
            for (i in 0 until num) {
                var tempArr: ByteArray
                if (i == num - 1) {
                    tempArr = ByteArray(data.size - i * 20)
                    System.arraycopy(data, i * 20, tempArr, 0, data.size - i * 20)
                } else {
                    tempArr = ByteArray(20)
                    System.arraycopy(data, i * 20, tempArr, 0, 20)
                }
                charaWrite.value = tempArr
                mBluetoothGatt.writeCharacteristic(charaWrite)
            }
        } else {
            charaWrite.value = data
            mBluetoothGatt.writeCharacteristic(charaWrite)
        }
    }

    private val HEX = "0123456789abcdef"
    fun bytes2hex(bytes: ByteArray): String? {
        val sb = StringBuilder(bytes.size * 2)
        for (b: Byte in bytes) {
            // 取出这个字节的高4位，然后与0x0f与运算，得到一个0-15之间的数据，通过HEX.charAt(0-15)即为16进制数
            sb.append(HEX[(b.toInt() shr 4) and 0x0f])
            // 取出这个字节的低位，与0x0f与运算，得到一个0-15之间的数据，通过HEX.charAt(0-15)即为16进制数
            sb.append(HEX[b.toInt() and 0x0f])
        }
        return sb.toString()
    }

    override fun onDestroy() {
        super.onDestroy()
        mBluetoothGatt.disconnect()
    }


}